package com.sduept.nwld.dataserver.controller.base.secondary;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;

import org.apache.commons.lang3.StringUtils;
import org.primefaces.event.FileUploadEvent;
import org.primefaces.event.NodeExpandEvent;
import org.primefaces.event.NodeSelectEvent;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.StreamedContent;
import org.primefaces.model.TreeNode;
import org.primefaces.model.UploadedFile;
import org.springframework.beans.factory.annotation.Autowired;

import com.sduept.bigdata.fault.manager.WaveFileAssistManager;
import com.sduept.bigdata.fault.manager.WaveFileManager;
import com.sduept.bigdata.fault.system.properties.FaultSystemProperties;
import com.sduept.bigdata.web.jsf.controller.AbstractController;
import com.sduept.cim.exception.WaveFileGetException;
import com.sduept.cim.model.core.Substation;
import com.sduept.cim.model.extend.ProtectWaveFile;
import com.sduept.cim.model.extend.protection.cfg.ProtectCfgAnalogChannel;
import com.sduept.cim.model.extend.protection.cfg.ProtectCfgDigitalChannel;
import com.sduept.cim.model.extend.protection.cfg.ProtectWaveRecord;
import com.sduept.cim.model.extend.wave.dmf.DmfAlarm;
import com.sduept.cim.model.protection.ProtectionEquipment;
import com.sduept.cim.model.wires.ACLineSegment;
import com.sduept.cim.model.wires.Breaker;
import com.sduept.cim.model.wires.BusbarSection;
import com.sduept.cim.model.wires.Compensator;
import com.sduept.cim.model.wires.PowerTransformer;
import com.sduept.cim.model.wires.TransformerWinding;
import com.sduept.cim.wave.service.DmfProtectCreateManager;
import com.sduept.cim.wave.service.ProtectCfgConfigureManager;
import com.sduept.cim.wave.service.ProtectWaveFileManager;
import com.sduept.core.entity.IdentifiedObject;
import com.sduept.bigdata.weather.map.MapDataCache;
import com.sduept.nwld.dataserver.manager.cim.CimManager;
import com.sduept.nwld.dataserver.util.LibTreeNode;
import com.sduept.nwld.wave.util.CfgChnsParserUtil;
import com.sduept.stardfile.parser.model.cfg.CfgColumnNumException;
import com.sduept.stardfile.parser.model.cfg.CfgTimeFormatException;
import com.sduept.utils.PingYinUtil;

@Named
@ViewScoped
public class ProtectionEquipmentWaveController extends AbstractController {

	/**
	 *
	 */
	private static final long serialVersionUID = 3647850204761792341L;
	@Autowired
	private MapDataCache cimChe;
	@Autowired
	private CimManager manager;
	@Autowired
	private ProtectCfgConfigureManager cfgMan;
	@Autowired
	private DmfProtectCreateManager dmfManager;
	@Autowired
	private ProtectWaveFileManager waveFileManager;
	@Autowired
	private WaveFileManager waManager;
	@Autowired
	private WaveFileAssistManager assistManager;
	@Autowired
	private FaultSystemProperties pros;
	private TreeNode root;
	private TreeNode currentSelect;
	private String filterStation;
	private String svgContent;
	private ProtectCfgAnalogChannel analogSelected = new ProtectCfgAnalogChannel();
	private List<ProtectCfgAnalogChannel> analogSelecteds = new ArrayList<ProtectCfgAnalogChannel>();
	private ProtectCfgDigitalChannel digitSelected = new ProtectCfgDigitalChannel();
	private List<ProtectCfgDigitalChannel> digitSelecteds = new ArrayList<ProtectCfgDigitalChannel>();
	private List<ProtectCfgAnalogChannel> anologInfo = new ArrayList<>();
	private List<ProtectCfgDigitalChannel> digitInfo = new ArrayList<>();
	public Map<String, List<String>> digitRelateDevice = new HashMap<>();
	private String stationId;
	private String ptId;
	private ProtectionEquipment selectedProtectEquipment;
	private List<ProtectWaveFile> waveFiles = new ArrayList<>();
	private String dmfMsg;
	private List<ProtectionEquipment> protectEquipments = new ArrayList<>();
	private ProtectionEquipment selectProtectEquipment;
	private int rowsCounts = 0;
	private Map<String, byte[]> uploadFileMap = new HashMap<>();
	private StreamedContent file;
	public static final String FILE_FORMAT_CFG = "cfg";
	public static final String FILE_FORMAT_DAT = "dat";

	@PostConstruct
	public void init() {
		initTree();
	}

	public void initTree() {
		root = new DefaultTreeNode();
		List<Substation> stations = cimChe.getS500List();
		Collections.sort(stations, new Comparator<Substation>() {
			@Override
			public int compare(Substation o1, Substation o2) {
				return PingYinUtil.getPingYin(o1.getName()).compareTo(PingYinUtil.getPingYin(o2.getName()));
			}
		});
		genStationTreeNode(stations);
	}

	public void autoCompleteStation(SelectEvent event) {
		Object item = event.getObject();
		if (null != item) {
			filterTree(item.toString());
		}
	}

	public void generteAll() {
		cfgMan.deleteAllCfgChanne();
		List<Substation> stations = cimChe.getS500List();
		for (Substation station : stations) {
			List<ProtectionEquipment> list = manager.getProtectionEquipmentsByStationId(station.getId());
			try {
				for (ProtectionEquipment pe : list) {
					cfgMan.generateProtectChannels(pe);
					dmfManager.createDmf(pe.getId());
				}
				addSuccessMessage("所有设备生成成功！");
			} catch (NumberFormatException e) {
				e.printStackTrace();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			} catch (IndexOutOfBoundsException e) {
				e.printStackTrace();
			} catch (WaveFileGetException e) {
				e.printStackTrace();
			} catch (SQLException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (CfgColumnNumException e) {
				e.printStackTrace();
			} catch (CfgTimeFormatException e) {
				e.printStackTrace();
			}
		}
	}

	public void createDmf() {
		if (currentSelect != null && currentSelect.getData() instanceof ProtectionEquipment) {
			ProtectionEquipment pe = (ProtectionEquipment) currentSelect.getData();
			dmfManager.createDmf(pe.getId());
			getMsgs(pe.getId());
			addSuccessMessage("生成dmf文件成功！");
		} else {
			addErrorMessage("无法生成dmf文件！");
		}

	}

	public void createCfg() {
		if (currentSelect != null && currentSelect.getData() instanceof ProtectionEquipment) {
			ProtectionEquipment pe = (ProtectionEquipment) currentSelect.getData();
			ProtectWaveRecord record = cfgMan.getById(pe.getId());
			try {
				record.setCfg(cfgMan.getWaveCfgConent(pe));
				cfgMan.saveProtectWaveRecord(record);
				addSuccessMessage("生成cfg文件成功！");
			} catch (FileNotFoundException e) {
				addErrorMessage("生成cfg文件失败！");
				e.printStackTrace();
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (WaveFileGetException e) {
				addErrorMessage("生成cfg文件失败！");
				e.printStackTrace();
			}
		} else {
			addErrorMessage("无法生成cfg文件！");
		}
	}

	public void resetgAnalogChannel() {
		for (ProtectCfgAnalogChannel channel : analogSelecteds) {
			channel.setEquipmentId(null);
			channel.setEquipmentName(null);
			channel.setEquipmentType(null);
			cfgMan.saveProtectCfgAnalogChannel(channel);
		}
		addSuccessMessage("重置通道成功！");
	}

	public void resetgDigitalChannel() {
		for (ProtectCfgDigitalChannel channel : digitSelecteds) {
			channel.setEquipmentId(null);
			channel.setEquipmentName(null);
			channel.setEquipmentType(null);
			cfgMan.saveProtectCfgDigitalChannel(channel);
		}
		addSuccessMessage("重置通道成功！");
	}

	public void autoGenarate() {
		if (currentSelect != null && currentSelect.getData() instanceof ProtectionEquipment) {
			ProtectionEquipment pe = (ProtectionEquipment) currentSelect.getData();
			try {
				cfgMan.reGenerateWaveChannels(pe);
				getWaveChannelInfo(ptId);
			} catch (WaveFileGetException e) {
				addErrorMessage("未找到录波配置文件" + e.fileName);
			} catch (NumberFormatException e) {
				e.printStackTrace();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			} catch (IndexOutOfBoundsException e) {
				e.printStackTrace();
			} catch (SQLException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (CfgColumnNumException e) {
				e.printStackTrace();
			} catch (CfgTimeFormatException e) {
				e.printStackTrace();
			}
		}
	}

	public void relationEquipment() {
		if (currentSelect != null && currentSelect.getData() instanceof ProtectionEquipment) {
			ProtectionEquipment pe = (ProtectionEquipment) currentSelect.getData();
			try {
				cfgMan.relationEquipment(pe);
				getWaveChannelInfo(pe.getId());
			} catch (Exception e) {
				addErrorMessage("更新出错：" + e.getMessage());
			}
			addSuccessMessage("更新通道成功");
		}
	}

	// 模拟通道关联设备
	public void getEquipmentByStation() {
		Map<String, Object> options = new HashMap<String, Object>();
		options.put("resizable", true);
		options.put("draggable", true);
		options.put("modal", false);
		options.put("width", 600);
		options.put("height", 400);
		Map<String, List<String>> params = new HashMap<>();
		List<String> s = new ArrayList<>();
		s.add(stationId);
		params.put("stationId", s);
		openDialog("/ui/common/equipment_selector_single",params, options);
	}

	public void onAnologSelectorChosen(SelectEvent event) {
		IdentifiedObject equipment = (IdentifiedObject) event.getObject();
		if (equipment != null) {
			for (ProtectCfgAnalogChannel channel : analogSelecteds) {
				channel.setEquipmentId(equipment.getId());
				channel.setEquipmentName(equipment.getName());
				channel.setEquipmentType(getEquipType(event.getObject()));
				cfgMan.saveProtectCfgAnalogChannel(channel);
			}

			addSuccessMessage("保存成功");
		}
	}

	private int getEquipType(Object object) {
		if (object instanceof ACLineSegment) {
			return CfgChnsParserUtil.TYPE_LINE;
		} else if (object instanceof BusbarSection) {
			return CfgChnsParserUtil.TYPE_BUSBAR;
		} else if (object instanceof Breaker) {
			return CfgChnsParserUtil.TYPE_BREAKER;
		} else if (object instanceof ProtectionEquipment) {
			return CfgChnsParserUtil.TYPE_PROTECT;
		} else if (object instanceof PowerTransformer) {
			return CfgChnsParserUtil.TYPE_POWER;
		} else if (object instanceof Compensator) {
			return CfgChnsParserUtil.TYPE_COMPEN;
		} else if (object instanceof TransformerWinding) {
			return CfgChnsParserUtil.TYPE_POWER;
		}
		return 0;
	}

	public void onDigitSelectorChosen(SelectEvent event) {
		IdentifiedObject equipment = (IdentifiedObject) event.getObject();
		for (ProtectCfgDigitalChannel channel : digitSelecteds) {
			channel.setEquipmentId(equipment.getId());
			channel.setEquipmentName(equipment.getName());
			channel.setEquipmentType(getEquipType(event.getObject()));
			cfgMan.saveProtectCfgDigitalChannel(channel);
		}
		addSuccessMessage("保存成功");
	}

	private void getWaveChannelInfo(String ptId) {
		// 根据id获取模拟通道和数字通道
		anologInfo = cfgMan.listProtectCfgAnalogChannelsByPtId(ptId);
		digitInfo = cfgMan.listProtectCfgDigitalChannelsByPtId(ptId);
	}

	private void genStationTreeNode(List<Substation> stations) {
		for (Substation s : stations) {
			new LibTreeNode("station", s, root);
		}
	}

	public void filterTree(String name) {
		root = new DefaultTreeNode();
		List<Substation> roots = manager.getStationByName(name);
		genStationTreeNode(roots);
	}

	public void onNodeExpand(NodeExpandEvent event) {
		TreeNode node = event.getTreeNode();
		node.getChildren().clear();
		if ("station".equals(node.getType())) {
			Substation station = (Substation) node.getData();
			List<ProtectionEquipment> list = manager.getProtectionEquipmentsByStationId(station.getId());
			for (ProtectionEquipment pe : list) {
				new LibTreeNode("wave", pe, node);
			}
		}
	}

	public void onNodeSelect(NodeSelectEvent event) {
		currentSelect = event.getTreeNode();
		protectEquipments.clear();
		if ("station".equals(currentSelect.getType())) {
			Substation sub = (Substation) currentSelect.getData();
			genSvgContent(sub.getId());
			List<ProtectionEquipment> list = manager.getProtectionEquipmentsByStationId(sub.getId());
			protectEquipments.addAll(list);
			ptId = null;
		} else {
			svgContent = "1";
			ProtectionEquipment pt = (ProtectionEquipment) currentSelect.getData();
			stationId = pt.getSubId().toString();
			ptId = pt.getId();
			getWaveChannelInfo(ptId);
			selectedProtectEquipment = pt;
			waveFiles = waveFileManager.listWaveFiles(selectedProtectEquipment.getId());
			getMsgs(ptId);
		}
	}

	private void getMsgs(String waveId) {
		dmfMsg = "";
		List<DmfAlarm> list = dmfManager.listDmfAlarmByWaveId(waveId);
		for (DmfAlarm alarm : list) {
			if (!StringUtils.isEmpty(alarm.getMsg())) {
				dmfMsg = dmfMsg + alarm.getMsg();
			}
		}
		rowsCounts = dmfMsg.split("\n\t").length;
	}

	private void genSvgContent(String stationId) {
		StringBuffer sb = new StringBuffer();
		File sf = new File(pros.getSvgBxPath() + stationId + ".svg");
		if (sf.exists()) {
			RandomAccessFile raf = null;
			try {
				raf = new RandomAccessFile(sf, "r");
				String lstr = raf.readLine();
				boolean startAdd = false;
				while (lstr != null) {
					if (startAdd) {
						lstr = new String(lstr.trim().getBytes("ISO-8859-1"), "utf-8");
						lstr = lstr.replaceAll("\"", "'");
						sb.append(lstr);
					} else {
						if (lstr.startsWith("<svg")) {
							startAdd = true;
							lstr = new String(lstr.trim().getBytes("ISO-8859-1"), "utf-8");
							lstr = lstr.replaceAll("\"", "'");
							sb.append(lstr);
						}
					}
					lstr = raf.readLine();
				}
				svgContent = sb.toString();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				try {
					raf.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

		} else {
			svgContent = "";
		}
	}

	public void resetUploadedFileMap() {
		uploadFileMap.clear();
	}

	/**
	 * 上传录波文件 由于这个方法是多线程调用uploadedFileList使用线程安全的集合
	 *
	 * @param event
	 */
	public void handleWaveFileUpload(FileUploadEvent event) {
		UploadedFile uf = event.getFile();
		String fileName = uf.getFileName();
		uploadFileMap.put(fileName, uf.getContents());
		if (uploadFileMap.size() == 2) {
			String stationPrivateId = selectedProtectEquipment.getPrivateStationId();
			String equipment = selectedProtectEquipment.getId();
			String dirPath = pros.getWaveFilePath() + stationPrivateId + File.separator + equipment
					+ File.separator;
			int status = -1;
			try {
				status = waManager.saveWaveFileAndGenerateRecord(selectedProtectEquipment, dirPath,
						uploadFileMap);
				getWaveChannelInfo(selectedProtectEquipment.getId());
				getMsgs(selectedProtectEquipment.getId());
				waveFiles = waveFileManager.listWaveFiles(selectedProtectEquipment.getId());
			} catch (Exception e) {
				e.printStackTrace();
			}
			if (status == 0)
				addSuccessMessage(fileName + "上传成功");
			else if (status == -1)
				addErrorMessage("上传文件列表存在异常");
			else if (status == 1)
				addErrorMessage("发生IO异常请联系管理员，谢谢");
			else
				addErrorMessage("发生未知异常");
		}
	}

	public void editAnologInfo() {
		if (analogSelecteds != null && analogSelecteds.size() > 0)
			analogSelected = analogSelecteds.get(0);
	}

	public void saveAnologInfo() {
		cfgMan.saveProtectCfgAnalogChannel(analogSelected);
		for (int i = 0; i < anologInfo.size(); i++) {
			if (anologInfo.get(i).getId().equals(analogSelected.getId())) {
				anologInfo.set(i, analogSelected);
				break;
			}
		}
		addSuccessMessage("保存成功！");
		selectProtectEquipment = null;
	}

	public void editDigitInfo() {
		if (digitSelecteds != null && digitSelecteds.size() > 0) {
			digitSelected = digitSelecteds.get(0);
		}
	}

	public void saveCfgDigitalChannel() {
		cfgMan.saveProtectCfgDigitalChannel(digitSelected);
		for (int i = 0; i < digitInfo.size(); i++) {
			if (digitInfo.get(i).getId().equals(digitSelected.getId())) {
				digitInfo.set(i, digitSelected);
				break;
			}
		}
		addSuccessMessage("保存成功！");
		selectProtectEquipment = null;
	}

	public String getFileName(String filePath) {
		String rtn = "";
		if (StringUtils.isEmpty(filePath)) {
			return rtn;
		}
		int pos = filePath.lastIndexOf("/");
		if (pos > -1) {
			rtn = filePath.substring(pos + 1, filePath.length());
		}
		return rtn;
	}

	public void deleteWaveFile(String id) {
		ProtectWaveFile file = waveFileManager.getProtectWaveFile(id);
		String path = pros.getWaveFilePath() + file.getPath();
		File f1 = new File(path + ".cfg");
		if (f1.isFile() && f1.exists())
			f1.delete();
		File f2 = new File(path + ".dat");
		if (f2.isFile() && f2.exists())
			f2.delete();
		waveFiles.remove(file);
		waveFileManager.deleteProtectWaveFileById(id);
		addSuccessMessage("删除成功！");
	}

	public void reSetFileStatus(String id) {
		waveFileManager.resetProtectWaveFile(id);
		addSuccessMessage("已经重新解析，请等待！");
	}

	public String seeDmf() {
		String result = "dmf信息为空";
		if (currentSelect != null && currentSelect.getData() instanceof ProtectionEquipment) {
			ProtectionEquipment pe = (ProtectionEquipment) currentSelect.getData();
			if (null == pe) {
				return result;
			}
			ProtectWaveRecord waveRecord = cfgMan.getById(pe.getId());
			if (null == waveRecord || StringUtils.isEmpty(waveRecord.getDmf())) {
				return result;
			}
			return waveRecord.getDmf();
		}
		return result;
	}

	public void prepareDownload(ProtectWaveFile wf) {
		FileInputStream fis = null;
		try {
			fis = assistManager.generateDownloadZipFile(wf);
			file = new DefaultStreamedContent(fis, "application/octet-stream", wf.getEquipment() + ".zip") ;
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		}
		if(file == null) {
			addErrorMessage("查找文件失败，无法下载");
		}
	}

	public TreeNode getRoot() {
		return root;
	}

	public void setRoot(TreeNode root) {
		this.root = root;
	}

	public String getFilterStation() {
		return filterStation;
	}

	public void setFilterStation(String filterStation) {
		this.filterStation = filterStation;
	}

	public TreeNode getCurrentSelect() {
		return currentSelect;
	}

	public void setCurrentSelect(TreeNode currentSelect) {
		this.currentSelect = currentSelect;
	}

	public ProtectCfgAnalogChannel getAnalogSelected() {
		return analogSelected;
	}

	public void setAnalogSelected(ProtectCfgAnalogChannel analogSelected) {
		this.analogSelected = analogSelected;
	}

	public List<ProtectCfgAnalogChannel> getAnalogSelecteds() {
		return analogSelecteds;
	}

	public void setAnalogSelecteds(List<ProtectCfgAnalogChannel> analogSelecteds) {
		this.analogSelecteds = analogSelecteds;
	}

	public ProtectCfgDigitalChannel getDigitSelected() {
		return digitSelected;
	}

	public void setDigitSelected(ProtectCfgDigitalChannel digitSelected) {
		this.digitSelected = digitSelected;
	}

	public List<ProtectCfgDigitalChannel> getDigitSelecteds() {
		return digitSelecteds;
	}

	public void setDigitSelecteds(List<ProtectCfgDigitalChannel> digitSelecteds) {
		this.digitSelecteds = digitSelecteds;
	}

	public List<ProtectCfgAnalogChannel> getAnologInfo() {
		return anologInfo;
	}

	public void setAnologInfo(List<ProtectCfgAnalogChannel> anologInfo) {
		this.anologInfo = anologInfo;
	}

	public List<ProtectCfgDigitalChannel> getDigitInfo() {
		return digitInfo;
	}

	public void setDigitInfo(List<ProtectCfgDigitalChannel> digitInfo) {
		this.digitInfo = digitInfo;
	}

	public String getDmfMsg() {
		return dmfMsg;
	}

	public void setDmfMsg(String dmfMsg) {
		this.dmfMsg = dmfMsg;
	}

	public String getSvgContent() {
		return svgContent;
	}

	public void setSvgContent(String svgContent) {
		this.svgContent = svgContent;
	}

	public ProtectionEquipment getSelectProtectEquipment() {
		return selectProtectEquipment;
	}

	public void setSelectProtectEquipment(ProtectionEquipment selectProtectEquipment) {
		this.selectProtectEquipment = selectProtectEquipment;
	}

	public int getRowsCounts() {
		return rowsCounts;
	}

	public void setRowsCounts(int rowsCounts) {
		this.rowsCounts = rowsCounts;
	}

	public ProtectionEquipment getSelectedProtectEquipment() {
		return selectedProtectEquipment;
	}

	public void setSelectedProtectEquipment(ProtectionEquipment selectedProtectEquipment) {
		this.selectedProtectEquipment = selectedProtectEquipment;
	}

	public List<ProtectionEquipment> getProtectEquipments() {
		return protectEquipments;
	}

	public void setProtectEquipments(List<ProtectionEquipment> protectEquipments) {
		this.protectEquipments = protectEquipments;
	}

	public List<ProtectWaveFile> getWaveFiles() {
		return waveFiles;
	}

	public void setWaveFiles(List<ProtectWaveFile> waveFiles) {
		this.waveFiles = waveFiles;
	}

	public StreamedContent getFile() {
		return file;
	}

	public void setFile(StreamedContent file) {
		this.file = file;
	}

}
